
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GLES/gl.h> /* For NDK*/
#include <android/log.h>
#include "utils.h"
#include "jade.h"


/* Following gluLookAt implementation is adapted from the
 * Mesa 3D Graphics library. http://www.mesa3d.org
 */
static void 
gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez,
        GLfloat centerx, GLfloat centery, GLfloat centerz,
	    GLfloat upx, GLfloat upy, GLfloat upz)
{
    GLfloat m[16];
    GLfloat x[3], y[3], z[3];
    GLfloat mag;

    /* Make rotation matrix */

    /* Z vector */
    z[0] = eyex - centerx;
    z[1] = eyey - centery;
    z[2] = eyez - centerz;
    mag = (float)sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
    if (mag) {			/* mpichler, 19950515 */
        z[0] /= mag;
        z[1] /= mag;
        z[2] /= mag;
    }

    /* Y vector */
    y[0] = upx;
    y[1] = upy;
    y[2] = upz;

    /* X vector = Y cross Z */
    x[0] = y[1] * z[2] - y[2] * z[1];
    x[1] = -y[0] * z[2] + y[2] * z[0];
    x[2] = y[0] * z[1] - y[1] * z[0];

    /* Recompute Y = Z cross X */
    y[0] = z[1] * x[2] - z[2] * x[1];
    y[1] = -z[0] * x[2] + z[2] * x[0];
    y[2] = z[0] * x[1] - z[1] * x[0];

    /* mpichler, 19950515 */
    /* cross product gives area of parallelogram, which is < 1.0 for
     * non-perpendicular unit-length vectors; so normalize x, y here
     */

    mag = (float)sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
    if (mag) {
        x[0] /= mag;
        x[1] /= mag;
        x[2] /= mag;
    }

    mag = (float)sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
    if (mag) {
        y[0] /= mag;
        y[1] /= mag;
        y[2] /= mag;
    }

#define M(row,col)  m[col*4+row]
    M(0, 0) = x[0];
    M(0, 1) = x[1];
    M(0, 2) = x[2];
    M(0, 3) = 0.0;
    M(1, 0) = y[0];
    M(1, 1) = y[1];
    M(1, 2) = y[2];
    M(1, 3) = 0.0;
    M(2, 0) = z[0];
    M(2, 1) = z[1];
    M(2, 2) = z[2];
    M(2, 3) = 0.0;
    M(3, 0) = 0.0;
    M(3, 1) = 0.0;
    M(3, 2) = 0.0;
    M(3, 3) = 1.0;
#undef M
    {
        int a;
        GLfixed fixedM[16];
        for (a = 0; a < 16; ++a)
            fixedM[a] = (GLfixed)(m[a] * 65536);
        glMultMatrixx(fixedM);
    }

    /* Translate Eye to Origin */
    glTranslatex((GLfixed)(-eyex * 65536),
                 (GLfixed)(-eyey * 65536),
                 (GLfixed)(-eyez * 65536));
}



jade_camera_t* jade_camera_create () {

    jade_camera_t *camera;

    camera = (jade_camera_t*)malloc (sizeof (jade_camera_t));
    if (camera == NULL)
        return NULL;

    camera->m_eyex = 0.0f;
    camera->m_eyey = 0.0f;
    camera->m_eyez = 0.0f;
    camera->m_centerx = 0.0f;
    camera->m_centery = 0.0f;
    camera->m_centerz = 0.0f;
    camera->m_upx = 0.0f;
    camera->m_upy = 1.0f;
    camera->m_upz = 0.0f;
    

    return camera;
    
}

void jade_camera_destroy (jade_camera_t* camera) {

    if (camera != NULL)
        FREEANDNULL (camera);

}

void jade_camera_set_eye (jade_camera_t *camera, GLfloat eyex, GLfloat eyey, GLfloat eyez) {

#ifdef FLOAT_ARG_FAIL
    camera->m_eyex = 0.0f;
    camera->m_eyey = 10.0f;
    camera->m_eyez = 30.0f;

#else

    camera->m_eyex = eyex;
    camera->m_eyey = eyey;
    camera->m_eyez = eyez;

#endif

}

void jade_camera_set_center (jade_camera_t *camera, GLfloat centerx, GLfloat centery, GLfloat centerz) {

    camera->m_centerx = centerx;
    camera->m_centery = centery;
    camera->m_centerz = centerz;
}

void jade_camera_set_up (jade_camera_t *camera, GLfloat upx, GLfloat upy, GLfloat upz) {

    camera->m_upx = upx;
    camera->m_upy = upy;
    camera->m_upz = upz;
}


void jade_camera_glulookat (jade_camera_t *camera) {

    gluLookAt(camera->m_eyex, camera->m_eyey, camera->m_eyez,
	          camera->m_centerx, camera->m_centery, camera->m_centerz,
	          camera->m_upx, camera->m_upy, camera->m_upz);

/*
    LOGD ("eyex = f%, eyey = %f, eyez = %f.\n", camera->m_eyex, camera->m_eyey, camera->m_eyez);
    gluLookAt(60.0f, 15.0f, 60.0f, 0.0f, 0.0f, 0.0f,
	          0.0f, 1.0f, 0.0f);
*/
/*
    gluLookAt(0.0f, 0.0f, 30.0f, 0.0f, 0.0f, 0.0f,
	          0.0f, 1.0f, 0.0f);
*/
}




